import 'package:kq_flutter_core_widget/utils/ex/string_ex.dart';
import 'package:lpinyin/lpinyin.dart';

import 'indexer.dart';

/// 数据索引工具
class IndexerUtil {
  /// 始终排在列表最顶端,可自己改为特定值
  static String alwaysTopSymbol = "★";

  /// 始终排在列表最底部,可自己改为特定值
  static String alwaysBottomSymbol = "#";

  /// 给数据排序，默认根据[Indexer.sortLetter]内容升序排列，其中有两个特殊字符[alwaysTopSymbol]和[alwaysBottomSymbol]。
  /// 如果[Indexer.sortLetter]获取内容为[alwaysTopSymbol],则始终排在最顶端，如果[Indexer.sortLetter]获取内容为
  /// [alwaysBottomSymbol],则始终排在最底端。通常情况下都无需主动给[Indexer.sortLetter]赋值，除非你想干预某个数据在列表的排序结果。
  ///
  /// [characterType]为字符大小写类型，指定排序根据大写还是小写排序。且此字段也用于生成[Indexer.sortLetter]和[Indexer.fullLetter]，当它们不存在时。
  ///
  /// [isIndexNumber] 是否索引数字，如果不索引，则全部放到[alwaysBottomSymbol]分组
  static List<T> sortData<T extends Indexer>({
    required List<T> data,
    CharacterType characterType = CharacterType.lowerCase,
    bool isIndexNumber = false,
  }) {
    _sortData(data, characterType, isIndexNumber);
    return data;
  }

  /// 根据给定[data]生成索引数据，如['★','A','B','C','D','1','2','#']
  ///
  /// [characterType]为字符大小写类型，此字段也用于生成[Indexer.sortLetter]和[Indexer.fullLetter]。
  ///
  /// [isIndexNumber]是否索引数字，如果索引，则根据[data]返回[0-9]中存在的索引数据
  static List<String> getIndexData<T extends Indexer>({
    required List<T> data,
    CharacterType characterType = CharacterType.lowerCase,
    bool isIndexNumber = false,
  }) {
    _sortData(data, characterType, isIndexNumber);
    List<String> indexData = [];
    for (T t in data) {
      if (t.sortLetter.isNullOrEmpty) {
        if (!indexData.contains(alwaysBottomSymbol)) {
          indexData.add(alwaysBottomSymbol);
        }
      } else if (!indexData.contains(t.sortLetter)) {
        indexData.add(t.sortLetter!);
      }
    }
    return indexData;
  }

  /// 根据给定[data]生成索引分组，内部已自动排序。
  ///
  /// [characterType]为字符大小写类型，用于生成[Indexer.sortLetter]和[Indexer.fullLetter]。
  ///
  /// [isIndexNumber]是否索引数字，如果索引，则根据[data]生成[0-9]中存在的索引分组
  static Map<String, List<T>> getSectionData<T extends Indexer>(
      {required List<T> data,
      CharacterType characterType = CharacterType.lowerCase,
      bool isIndexNumber = false}) {
    _sortData(data, characterType, isIndexNumber);
    Map<String, List<T>> sectionData = {};
    for (T t in data) {
      if (t.sortLetter.isNullOrEmpty) {
        if (!sectionData.containsKey(alwaysBottomSymbol)) {
          sectionData[alwaysBottomSymbol] = [t];
        }
      } else if (!sectionData.containsKey(t.sortLetter)) {
        sectionData[t.sortLetter!] = [t];
      } else {
        sectionData.update(t.sortLetter!, (value) {
          value.add(t);
          return value;
        });
      }
    }

    return sectionData;
  }

  /// 排序
  static _sortData<T extends Indexer>(
    List<T> data,
    CharacterType type,
    bool isIndexNumber,
  ) {
    data.sort((left, right) {
      _swap(left, isIndexNumber, type);
      _swap(right, isIndexNumber, type);

      if (left.sortLetter == alwaysTopSymbol) {
        if (right.sortLetter == alwaysTopSymbol) {
          return (left.fullLetter ?? "").compareTo(right.fullLetter ?? "");
        }
        return -1;
      } else if (left.sortLetter != alwaysTopSymbol &&
          right.sortLetter == alwaysTopSymbol) {
        return 1;
      } else if (left.sortLetter == alwaysBottomSymbol) {
        if (right.sortLetter == alwaysBottomSymbol) {
          return (left.fullLetter ?? "").compareTo(right.fullLetter ?? "");
        }
        return 1;
      } else if (right.sortLetter == alwaysBottomSymbol) {
        return -1;
      } else {
        return (left.sortLetter ?? "").compareTo(right.sortLetter ?? "");
      }
    });
  }

  /// 获取字符串首字拼音
  static String? _getSelling<T extends Indexer>(T t) {
    String? latter = t.getFullName();
    if (latter.isNullOrEmpty) {
      return null;
    }
    return PinyinHelper.getFirstWordPinyin(latter!);
  }

  /// 根据全拼获取首字母
  static String _getFirstLetter(
      String pinyin, bool isIndexNumber, CharacterType type) {
    if (pinyin.isNullOrEmpty) {
      return alwaysBottomSymbol;
    }
    String sortString = pinyin.substring(0, 1);
    if (RegExp(r"[A-Za-z]").hasMatch(sortString)) {
      return type == CharacterType.upperCase
          ? sortString.toUpperCase()
          : sortString.toLowerCase();
    } else if (isIndexNumber && RegExp(r"\d").hasMatch(sortString)) {
      return sortString;
    } else {
      return alwaysBottomSymbol;
    }
  }

  /// 数据转化
  static _swap<T extends Indexer>(T t, bool isIndexNumber, CharacterType type) {
    t.fullLetter ??= _getSelling(t);
    if (t.fullLetter != null) {
      t.sortLetter ??= _getFirstLetter(t.fullLetter!, isIndexNumber, type);
      if (t.sortLetter.isNullOrEmpty) {
        t.sortLetter = alwaysBottomSymbol;
      }
    } else {
      t.sortLetter = alwaysBottomSymbol;
    }
  }
}

/// 字符大小写类型
enum CharacterType {
  /// 大写
  upperCase,

  /// 小写
  lowerCase
}
